package repositories;

import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateCallback;

import users.Person;
import books.BookInfo;
import books.BookRequestsInfo;
import books.BookReservation;

/**
 */
public class ReservationRepository extends HibernateGenericDAO<BookRequestsInfo> implements
        GenericRepository<BookRequestsInfo> {

    private static final long serialVersionUID = 1L;

    @Override
    protected Class<BookRequestsInfo> getDomainClass() {
        return BookRequestsInfo.class;
    }

    public BookReservation getReservationOf(final BookInfo aBookInfo) {
        return (BookReservation) this.getHibernateTemplate().execute(new HibernateCallback<Object>() {
            @Override
            public BookReservation doInHibernate(final Session session) throws HibernateException, SQLException {
                Criteria criteria = session.createCriteria(BookRequestsInfo.class);
                criteria.add(Restrictions.eq("book", aBookInfo));
                BookRequestsInfo result = (BookRequestsInfo) criteria.uniqueResult();
                return result.getReservedTo();
            }
        });
    }

    public BookRequestsInfo getRequestsOf(final BookInfo aBookInfo) {
        return (BookRequestsInfo) this.getHibernateTemplate().execute(new HibernateCallback<Object>() {
            @Override
            public BookRequestsInfo doInHibernate(final Session session) throws HibernateException, SQLException {
                Criteria criteria = session.createCriteria(BookRequestsInfo.class);
                criteria.add(Restrictions.eq("book.id", aBookInfo.getId()));
                return (BookRequestsInfo) criteria.uniqueResult();
            }
        });
    }

    @SuppressWarnings("unchecked")
    public List<BookReservation> getReservationsOf(final Person aPerson) {
        return (List<BookReservation>) this.getHibernateTemplate().execute(new HibernateCallback<Object>() {
            @Override
            public List<BookReservation> doInHibernate(final Session session) throws HibernateException, SQLException {
                Query query = session.createQuery("select bri.reservedTo " + "from BookRequestsInfo as bri "
                        + " join bri.reservedTo as res " + "where res.person = :personparam");

                query.setParameter("personparam", aPerson);
                return query.list();
            }
        });
    }

    @SuppressWarnings("unchecked")
    public List<BookReservation> findSatisfiedReservations() {
        return (List<BookReservation>) this.getHibernateTemplate().execute(new HibernateCallback<Object>() {
            @Override
            public List<BookReservation> doInHibernate(final Session session) throws HibernateException, SQLException {
                Query query = session.createQuery("select bri.reservedTo " + "from BookRequestsInfo as bri "
                        + " join bri.reservedTo as res " + "where res.satisfied = true");

                return query.list();
            }
        });
    }
}
